# Copyright (c) 2024-2025 Ziqi Fan
# SPDX-License-Identifier: Apache-2.0

from isaaclab.utils import configclass
from isaaclab_rl.rsl_rl import RslRlOnPolicyRunnerCfg, RslRlPpoActorCriticCfg, RslRlPpoAlgorithmCfg


@configclass
class DuckRoughPPORunnerCfg(RslRlOnPolicyRunnerCfg):
    num_steps_per_env = 24
    # 通常10000就能让四足运动的任务收敛
    max_iterations = 3000
    # 每训练save_interval次保存一次模型
    save_interval = 50
    experiment_name = "duck"
    # 是否使用“经验归一化”方法对观测数据进行标准化处理。
    empirical_normalization = False
    # 策略网络配置
    policy = RslRlPpoActorCriticCfg(
        init_noise_std=1.0,  # 初始动作分布的标准差（探索性）
        actor_hidden_dims=[512, 256, 128],  # actor网络隐藏层维度
        critic_hidden_dims=[512, 256, 128], # critic网络隐藏层维度
        activation="elu",    # 激活函数类型（ELU）
    )
    # PPO算法配置
    algorithm = RslRlPpoAlgorithmCfg(
        value_loss_coef=1.0,    # 价值函数损失系数
        use_clipped_value_loss=True,  # 是否使用裁剪的价值损失
        clip_param=0.2,         # PPO裁剪参数（epsilon）
        entropy_coef=0.008,     # 熵损失系数（鼓励探索）
        num_learning_epochs=5,  # 每次采样后的学习轮数
        num_mini_batches=4,     # 每次采样分成的mini-batch数量
        learning_rate=1.0e-3,   # 学习率
        schedule="adaptive",    # 学习率调度方式（自适应）
        gamma=0.99,  # 折扣因子（未来奖励权重）
        lam=0.95,    # GAE参数（优势估计的平滑系数）
        desired_kl=0.01,    # 期望KL散度（用于自适应学习率）
        max_grad_norm=1.0,  # 最大梯度范数（梯度裁剪防止爆炸）
    )


@configclass
class DuckFlatPPORunnerCfg(DuckRoughPPORunnerCfg):
    def __post_init__(self):
        super().__post_init__()

        self.max_iterations = 10000
        self.experiment_name = "duck"
